<template>
  <div class="image-upload-cropper">
    <el-upload
      class="uploader-container"
      :action="uploadAction"
      :headers="uploadHeaders"
      :show-file-list="false"
      :before-upload="beforeUpload"
      :on-success="handleUploadSuccess"
      :on-error="handleUploadError"
      :on-change="handleFileChange"
      accept="image/*"
      :http-request="customHttpRequest"
    >
      <div v-if="localImageUrl" class="image-preview">
        <img :src="localImageUrl" class="preview-image" />
        <div class="image-overlay">
          <el-icon><Refresh /></el-icon>
          <span class="overlay-text">点击更换图片</span>
        </div>
      </div>
      <div v-else class="upload-placeholder">
        <el-icon><Plus /></el-icon>
        <div class="upload-text">点击上传图片</div>
        <div v-if="hint" class="upload-hint">{{ hint }}</div>
      </div>
    </el-upload>

    <div v-if="localImageUrl" class="image-actions">
      <el-button size="small" type="primary" @click="handlePreview">
        <el-icon><ZoomIn /></el-icon>
        预览
      </el-button>
      <el-button size="small" type="danger" @click="handleRemove">
        <el-icon><Delete /></el-icon>
        删除
      </el-button>
    </div>

    <!-- 裁剪对话框 -->
    <el-dialog
      v-model="cropperDialogVisible"
      title="图片裁剪"
      width="800px"
      :close-on-click-modal="false"
      @close="closeCropperDialog"
    >
      <div class="cropper-content">
        <VuePictureCropper
          :width="cropperWidth"
          :height="cropperHeight"
          :img="cropperImg"
          :options="{
            viewMode: 1,
            aspectRatio: aspectRatioNumber,
            autoCropArea: 1,
            responsive: true,
            background: false
          }"
          ref="cropperRef"
        />
      </div>
      <template #footer>
        <el-button @click="cropperDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="confirmCrop" :loading="cropping">
          确定裁剪并上传
        </el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, watch, computed } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { Plus, Refresh, ZoomIn, Delete } from '@element-plus/icons-vue';
import { useTokenStore } from '@/stores/useTokenStore';
import axios from 'axios';
import VuePictureCropper, { cropper } from 'vue-picture-cropper';
import 'cropperjs/dist/cropper.css';

const props = defineProps({
  imageUrl: {
    type: String,
    default: ''
  },
  aspectRatio: {
    type: String, 
    default: '1:1'
  },
  hint: {
    type: String,
    default: ''
  }
});

const emit = defineEmits(['update:imageUrl']);

const localImageUrl = ref(props.imageUrl);
const cropperDialogVisible = ref(false);
const cropperImg = ref('');
const cropping = ref(false);
const rawFile = ref(null); // 存储原始文件对象
const cropperRef = ref(null); // vue-picture-cropper 实例引用

// 确保 aspectRatio 始终是 "宽:高" 格式的字符串
const safeAspectRatioString = computed(() => {
  let ratio = props.aspectRatio;
  if (typeof ratio === 'number') {
    ratio = `${ratio}:1`;
  } else if (typeof ratio !== 'string' || !ratio.includes(':')) {
    // 如果不是字符串或者不包含冒号，则使用默认值
    ratio = '1:1';
  }
  return ratio;
});

// 计算裁剪比例
const aspectRatioNumber = computed(() => {
  const parts = safeAspectRatioString.value.split(':');
  if (parts.length === 2 && !isNaN(parseInt(parts[0])) && !isNaN(parseInt(parts[1])) && parseInt(parts[1]) !== 0) {
    return parseInt(parts[0]) / parseInt(parts[1]);
  }
  return 1; // 默认 1:1 比例，如果解析失败或分母为0
});

// 计算裁剪尺寸以适应预览框，并保持比例
const cropperWidth = computed(() => {
  const parts = safeAspectRatioString.value.split(':');
  const ratio = parseInt(parts[0]) / parseInt(parts[1]);
  // 假设裁剪对话框宽度为 760px (800px - 2*padding)，我们根据比例计算高度
  // 或设定最大宽高
  const maxWidth = 700;
  const maxHeight = 400;

  let width = maxWidth;
  let height = maxWidth / ratio;

  if (height > maxHeight) {
    height = maxHeight;
    width = maxHeight * ratio;
  }
  return width;
});

const cropperHeight = computed(() => {
  const parts = safeAspectRatioString.value.split(':');
  const ratio = parseInt(parts[0]) / parseInt(parts[1]);
  const maxWidth = 700;
  const maxHeight = 400;

  let width = maxWidth;
  let height = maxWidth / ratio;

  if (height > maxHeight) {
    height = maxHeight;
    width = maxHeight * ratio;
  }
  return height;
});

// 上传配置
const uploadAction =   'http://localhost:1750/api/common/admin/upload'; 
const uploadHeaders = {
  'Authorization':  + useTokenStore().token
};

// 监听外部 imageUrl 变化
watch(() => props.imageUrl, (newVal) => {
  localImageUrl.value = newVal;
}, { immediate: true });

// 上传前处理，用于打开裁剪对话框
const beforeUpload = (file) => {
  const isImage = file.type.startsWith('image/');
  const isLt2M = file.size / 1024 / 1024 < 2;

  if (!isImage) {
    ElMessage.error('只能上传图片文件!');
    return false;
  }
  if (!isLt2M) {
    ElMessage.error('图片大小不能超过 2MB!');
    return false;
  }
  
  rawFile.value = file;
  // 使用 FileReader 读取文件以获取 Data URL 作为裁剪组件的图片源
  const reader = new FileReader();
  reader.onload = (e) => {
    cropperImg.value = e.target.result;
    cropperDialogVisible.value = true;
  };
  reader.readAsDataURL(file);

  return false; // 阻止 el-upload 自动上传
};

// 文件选择变化时触发，用于触发裁剪
const handleFileChange = (file) => {
  if (file.raw) {
    // 兼容手动拖拽或选择文件
    beforeUpload(file.raw);
  }
};

// 确认裁剪并上传
const confirmCrop = async () => {
  if (!cropperRef.value) {
    ElMessage.error('裁剪组件未准备好');
    return;
  }
  
  cropping.value = true;
  try {
    const blob = await cropper.getBlob();
    if (!blob) {
      ElMessage.error('请先裁剪图片');
      cropping.value = false;
      return;
    }
    
    const formData = new FormData();
    formData.append('file', blob, rawFile.value.name); // 'file' 对应后端接收文件的字段名

    const response = await axios.post(uploadAction, formData, {
      headers: {
        ...uploadHeaders,
        'Content-Type': 'multipart/form-data' // 必须设置，axios 会自动处理 boundary
      }
    });

    if (response.data.code === 200) {
      const newImageUrl = response.data.data.url || response.data.data; // 假设后端返回的数据结构
      localImageUrl.value = newImageUrl;
      emit('update:imageUrl', newImageUrl);
      ElMessage.success('图片上传成功');
      cropperDialogVisible.value = false;
    } else {
      ElMessage.error(response.data.message || '图片上传失败');
    }
  } catch (error) {
    console.error('裁剪或上传失败:', error);
    ElMessage.error('裁剪或上传失败，请重试');
  }
  cropping.value = false;
};

const handleUploadSuccess = (response) => {
  // 实际上不会被调用，因为我们阻止了自动上传
};

const handleUploadError = (error) => {
  // 实际上不会被调用
  console.error('上传失败:', error);
  ElMessage.error('上传失败，请重试');
};

const customHttpRequest = () => {
  // 阻止 el-upload 的默认上传行为
  return Promise.resolve();
};

const handlePreview = () => {
  if (localImageUrl.value) {
    window.open(localImageUrl.value, '_blank');
  } else {
    ElMessage.warning('没有图片可预览');
  }
};

const handleRemove = () => {
  ElMessageBox.confirm('确定要删除当前图片吗？', '提示', {
    type: 'warning'
  }).then(() => {
    localImageUrl.value = '';
    emit('update:imageUrl', '');
    ElMessage.success('图片已删除');
  }).catch(() => {});
};

const closeCropperDialog = () => {
  cropperImg.value = '';
  rawFile.value = null;
};
</script>

<style scoped>
.image-upload-cropper {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
}

.uploader-container {
  width: 100%;
}

.upload-placeholder {
  width: 180px; /* 默认宽度 */
  height: 100px; /* 默认高度 */
  border: 2px dashed #d9d9d9;
  border-radius: 8px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: #8c939d;
  transition: border-color 0.3s ease;
}

.upload-placeholder:hover {
  border-color: #409eff;
}

.upload-placeholder .el-icon {
  font-size: 28px;
  margin-bottom: 8px;
}

.upload-text {
  font-size: 16px;
  margin-bottom: 4px;
}

.upload-hint {
  font-size: 12px;
  color: #c0c4cc;
}

.image-preview {
  position: relative;
  width: 180px; /* 与上传占位符保持一致 */
  height: 100px; /* 与上传占位符保持一致 */
  border-radius: 8px;
  overflow: hidden;
  border: 2px solid #d9d9d9;
  cursor: pointer;
}

.preview-image {
  width: 100%;
  height: 100%;
  object-fit: cover; /* 确保图片覆盖整个容器 */
  transition: transform 0.3s ease;
}

.image-preview:hover .preview-image {
  transform: scale(1.05);
}

.image-preview .image-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: white;
  opacity: 0;
  transition: opacity 0.3s ease;
}

.image-preview:hover .image-overlay {
  opacity: 1;
}

.image-overlay .el-icon {
  font-size: 24px;
  margin-bottom: 5px;
}

.overlay-text {
  font-size: 14px;
}

.image-actions {
  display: flex;
  gap: 8px;
}

.cropper-content {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 400px; /* 裁剪区域的固定高度 */
  background-color: #f5f7fa;
  border-radius: 8px;
  overflow: hidden;
  position: relative;
}

/* vue-picture-cropper 样式 */
:deep(.vue-picture-cropper) {
  width: 100%;
  height: 100%;
}
</style> 